import { app, shell, BrowserWindow, ipcMain, Menu, screen, powerMonitor } from 'electron'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'
import { update } from './update' //自动升级
import { initSql } from './sql' //自动升级
import { getMacAddress } from './getMacAddress'
import { join, resolve } from 'path'

//electron-log 主进程使用示例
import log from 'electron-log/main';

const { Worker } = require('worker_threads')
//禁用当前程序的硬件加速 防止报错gpu_init.cc(523)] Passthrough is not supported, GL is disabled, ANGLE is
app.disableHardwareAcceleration()
log.transports.file.maxSize = 5 * 1024 * 1024; //  设置日志文件最大大小为 5MB 超出后会生成.old 如果再超出则会被删除


log.transports.file.resolvePathFn = () => join('logs', '/main.log');
// // Optional, initialize the logger for any renderer process
log.initialize();

log.info('Log from the main process4');
//监听系统的唤醒事件，并在唤醒后刷新页面或重新初始化应用：防止睡眠白屏
powerMonitor.on('resume', () => {
  log.info('System resumed from sleep');
  mainWindow.reload();
});
const { exec } = require('child_process');
const { Jimp } = require('jimp'); //jimp 将图片转为bmp格式
const ffi = require('koffi');

/*寺冈*/
let dllFilePath = '../../resources/pos_ad_dll.dll';
let dllPath = resolve(__dirname, dllFilePath)

if (process.env.NODE_ENV !== 'development') { // 确保在生产环境中能够访问未被打包进asar存档的DLL
  dllPath = join(__dirname, dllFilePath).replace('app.asar', 'app.asar.unpacked');
}
const lib1 = ffi.load(dllPath);//加载dll动态库
const sendTareFunc = lib1.func('int send_tare(char *rbuf)')//调用动态库中的去皮函数
const sendZeroFunc = lib1.func('int send_zero()')//调用动态库中的置零函数
const printFunc = lib1.func('int PrintBitmap(char* file) ') //打印函数
let tareBuffer = Buffer.alloc(128, 0); //皮重
/*寺冈end*/

/*托利多freshway*/
let TLD_dllFilePath = '../../resources/tuoliduo/pos_ad_dll.dll';
let TLD_dllPath = resolve(__dirname, TLD_dllFilePath)

if (process.env.NODE_ENV !== 'development') { // 确保在生产环境中能够访问未被打包进asar存档的DLL
  TLD_dllPath = join(__dirname, TLD_dllFilePath).replace('app.asar', 'app.asar.unpacked');
}
const lib2 = ffi.load(TLD_dllPath);//加载dll动态库

const TLD_sendTareFunc = lib2.func('int send_tare(char *rbuf)')//调用动态库中的去皮函数
const TLD_sendZeroFunc = lib2.func('int send_zero()')//调用动态库中的置零函数
const TLD_printFunc = lib2.func('int PrintBitmapFile(char* BmpFileName,int LabelAngle)') //打印函数
const TDL_BeginPrint = lib2.func('int BeginPrint(int PrintType)')
let TLD_tareBuffer = Buffer.alloc(12, 0); //皮重
/*托利多end*/



let worker   //新建一个进程(打印、读称)
let currentScaleType = '1' //当前称类型 默认为寺冈（1寺冈 2托利多）

//设置秤类型
ipcMain.on('set-scale-type', (_, type) => {
  //console.log('set-scale-type!')
  currentScaleType = type
})






ipcMain.on('read-weight', () => {
  let workerPath = resolve(__dirname, '../../resources/weightReaderWorker.js')
  if (!(process.env.NODE_ENV === 'development')) { //dll文件不打包，确保在生产环境中能够访问未被打包进asar存档的DLL
    workerPath = workerPath.replace('app.asar', 'app.asar.unpacked');
  }
  if (worker) { //如果线程存在，首先关闭线程，防止切换称类型时 线程没有关闭
    //console.log('worker',worker)
    worker.terminate()
  }

  worker = new Worker(workerPath);
  worker.postMessage({ text: 'startReadingWeight', currentScaleType }) //给worker进程发送读重消息

  worker.on('message', (obj) => { // 接收到worker进程的消息
    //console.log(obj);
    if (obj.weight !== undefined) {
      mainWindow.webContents.send('get-weight', { weight: obj.weight, tare: obj.tare });
      secondWindow?.webContents.send('get-weight-secondscreen', { weight: obj.weight, tare: obj.tare });
    }


  });

  worker.on('error', (err) => {
    console.error('Worker error:', err);
  });

  worker.on('exit', (code) => {
    if (code !== 0) {
      console.error(`Worker stopped with exit code ${code}`);
    }
  });
})


//去皮
ipcMain.handle('send-tare', async (_, weight) => {
  if (currentScaleType == '1') { //寺冈
    if (sendTareFunc(weight + '') == 240) {
      return tareBuffer.subarray(1, 7).toString('ascii').trim().replace(/[\x00-\x1F]/g, '')
    } else {
      console.log('sendtare-fail')//去皮失败
      throw new Error('send-tare-fail'); // 抛出错误，这将拒绝Promise
    }
  } else if (currentScaleType == '2') { //托利多
    if (TLD_sendTareFunc(weight + '') == 240) {
      return TLD_tareBuffer.subarray(1, 7).toString('ascii').trim().replace(/[\x00-\x1F]/g, '')
    } else {
      console.log('sendtare-fail')//去皮失败
      throw new Error('send-tare-fail'); // 抛出错误，这将拒绝Promise
    }
  }
  throw new Error('send-tare-fail')

})



//置零

ipcMain.handle('send-zero', () => {
  if (currentScaleType == '1') { //寺冈
    if (sendZeroFunc() != 240) {
      throw new Error('send-zero-fail'); // 置零失败
    }
  } else if (currentScaleType == '2') { //托利多
    if (TLD_sendZeroFunc() != 240) {
      throw new Error('send-zero-fail'); // 置零失败
    }
  }


})



//打印
ipcMain.handle('send-print', async (_, req) => {

  const imageBuffer = Buffer.from(req.data, 'base64');
  try {
    const image = await Jimp.read(imageBuffer)

    await image.write(resolve('./printtemp.bmp'));//注意这里必须同步，否则会造成打印上一张图片的bug

    if (currentScaleType == '1') { //寺冈
      let res = printFunc(resolve('./printtemp.bmp'))
      if (res != 240) {
        throw new Error('print-fail'); // 打印失败
      }
    } else if (currentScaleType == '2') { //托利多

     


      let res = TLD_printFunc(resolve('./printtemp.bmp'), 0)

      if (res != 240) {

        throw new Error('print-fail'); // 打印失败
      }
      TDL_BeginPrint(7) //开始打印
      TDL_BeginPrint(8)//切纸

    }


  } catch (error) {
    console.log('jimp-error')
  }
})



//better-sqlite3 数据库
initSql()






let mainWindow: BrowserWindow
let secondWindow: BrowserWindow //副屏窗口
let intervalId
function createWindow(): void {
  // const { width: screenWidth } = screen.getPrimaryDisplay().workAreaSize;
  const displays = screen.getAllDisplays(); // 获取所有显示屏
  if (displays.length < 1) {
    console.log('No displays found!');
  }
  // 主窗口显示在主屏
  const primaryDisplay = screen.getPrimaryDisplay();
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 1024,
    height: 768,
    x: primaryDisplay.bounds.x,
    y: primaryDisplay.bounds.y,
    show: false,
    alwaysOnTop: true, // TODO: 临时注释
    fullscreen: true,
    autoHideMenuBar: true,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false,
      webSecurity: false,//禁用同源策略

    }
  })
  const secondDisplay = displays.find(display => display.id !== primaryDisplay.id);
  secondWindow = new BrowserWindow({
    width: 1024,
    height: 768,
    x: secondDisplay?.bounds.x,
    y: secondDisplay?.bounds.y,
    show: false,
    alwaysOnTop: false,
    fullscreen: true, //临时设为false
    autoHideMenuBar: true,//临时设为false
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false,
      webSecurity: false,//禁用同源策略

    }
  })






  //
  mainWindow.on('ready-to-show', () => {
    //console.log('ready-to-show')
    // mainWindow.webContents.openDevTools()
    mainWindow.show()
    //自动升级
    try {
      update(mainWindow)
    } catch (error) {
      console.log(error)
    }

  })

  secondWindow.on('ready-to-show', () => {

    //secondWindow.webContents.openDevTools()
    secondWindow.show()
  })


  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  // HMR for renderer base on electron-vite cli.
  // Load the remote URL for development or the local html file for production.
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    // console.log(process.env)
    console.log('dev~')
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
    secondWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/secondscreen.html`)
    // console.log(`${process.env['ELECTRON_RENDERER_URL']}/index`)
    // secondWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/#/index`)
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
    secondWindow.loadFile(join(__dirname, '../renderer/secondscreen.html'))
    // secondWindow.loadURL('http://localhost:5173/#index')
  }
}
// 检查是否已经有一个实例在运行
const gotTheLock = app.requestSingleInstanceLock();

if (!gotTheLock) {
  // 如果已经有实例在运行，直接退出
  app.quit();
} else {
  app.on('second-instance', () => {
    // 当第二个实例启动时，激活当前窗口
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore();
      mainWindow.focus();
    }
  });
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
Menu.setApplicationMenu(null)
app.whenReady().then(() => {
  electronApp.setAppUserModelId('com.electron')
  createWindow()

  // 启动定时器
  intervalId = setInterval(() => {
    const currentTime = new Date().getTime()

    mainWindow.webContents.send('interval-tick', currentTime);

  }, 1000); // 每 1000ms 执行一次


  // Default open or close DevTools by F12 in development
  // and ignore CommandOrControl + R in production.
  // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })



  //获取设备id  (这里改为使用mac地址)
  ipcMain.handle('getUUID', async () => {
    let uuid
    try {
      //uuid = await getUUID()
      uuid = await getMacAddress().split(':').join('').toUpperCase()

    } catch (err) {
      console.log(err)
    }
    return uuid

  })

  //获取mac地址
  ipcMain.handle('getMacAddress', async () => {
    let uuid
    try {
      uuid = await getMacAddress()
    } catch (err) {
      console.log(err)
    }
    return uuid

  })

  //获取文件
  ipcMain.on('get-files', (_, data) => {

    secondWindow?.webContents.send('get-file-list', data)
  })



  //打开浏览器控制台
  ipcMain.on('open-main-window-devtools', () => {
    console.log('open-main-window-devtools~')
    mainWindow.webContents.openDevTools()
    secondWindow?.webContents.openDevTools()
  })
  //最小化窗口
  ipcMain.on('minimize-window', () => {
    const win = BrowserWindow.getFocusedWindow()
    if (win) {
      win.minimize()
    }
  })

  //退出程序
  ipcMain.on('close-window', () => {
    app.quit()
  })

  //关闭计算机
  ipcMain.on('shutdown-computer', () => {
    exec('shutdown /s /t 0', (err) => {
      if (err) {
        console.error(`执行失败: ${err}`);
        return;
      }

    });
  })


  //更新shoppingCarDatanew
  ipcMain.on('secondwindow-shoppingcardata', (_, data) => {
    secondWindow?.webContents.send('secondwindow-shoppingcardata', JSON.parse(data))
  })


  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })


  mainWindow.on('close', (_) => {
    if (worker) {

      worker.postMessage({ text: 'endReadingWeight' })
      worker.terminate(); // 终止 Worker 线程
    }

    app.quit(); // 退出应用

  })
})



app.on('before-quit', () => {
  console.log('before-quit')
  if (worker) {
    worker.postMessage({ text: 'endReadingWeight' })
  }
  clearTime()
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  console.log('window-all-closed')
  if (worker) {
    worker.postMessage({ text: 'endReadingWeight' })
  }
  if (process.platform !== 'darwin') {

    app.quit()
  }
})
process.on('uncaughtException', (err) => {
  console.error('uncaughtException8:', err);
  // 执行必要的清理工作
});

process.on('unhandledRejection', (reason, _) => {
  console.error('unhandleReject!:', reason);
  // 执行必要的清理工作
});


//监听渲染进程崩溃
//@ts-ignore
app.on("render-process-gone", (_e, w, d) => {
  if (d.reason == "crashed") {
    console.log("渲染进程崩溃，正在重启...");
    w.reload(); // 重新加载窗口
  } else {
    log.error(
      "渲染进程崩溃:  ",
      `${new Date()} 渲染进程被杀死，原因: ${d.reason}\n`
    );
    w.reload(); // 重新加载窗口
  }
});





//设置电脑本地时间为服务器时间
ipcMain.on('set-system-time', (_, serverTime) => {

  const dateCmd = `date ${serverTime.split(' ')[0]}`;
  const timeCmd = `time ${serverTime.split(' ')[1]}`;

  exec(dateCmd, (err, _stdout, stderr) => {
    if (err) {
      console.error(`Error setting system date: ${stderr}`);
      return;
    }
    exec(timeCmd, (err, _stdout, stderr) => {
      if (err) {
        console.error(`Error setting system time: ${stderr}`);

      } else {
        console.log('System time updated successfully.');

      }
    });
  });
});


//关闭定时器
function clearTime() {
  if (intervalId) {
    clearInterval(intervalId); // 关闭定时器

  }
}